#include "grid.h"

int
getNMine(const Grille * jeu)
{
	return jeu->nMine;
}

int
getDimX(const Grille * jeu)
{
	return jeu->dimx;
}

int
getDimY(const Grille * jeu)
{
	return jeu->dimy;
}

void
setNMine(Grille * jeu, const int mines)
{
	jeu->nMine = mines;
}

void
setDimX(Grille * jeu, const int dimx)
{
	jeu->dimx = dimx;
}

void
setDimY(Grille * jeu, const int dimy)
{
	jeu->dimy = dimy;
}

Case getCase(const Grille *jeu, const int x, const int y)
{
	assert(x >= 1 && x <= getDimX(jeu)-2);
	assert(y >= 1 && y <= getDimY(jeu)-2);
    return jeu->cases[y*jeu->dimx+x];
}

Case* getCasePtr(const Grille *jeu, const int x, const int y)
{
    return &jeu->cases[y*jeu->dimx+x];
}

void
initGrille(Grille * jeu, const int dimx, const int dimy, const int nmine)
{
	int i;
	int dimension;
	dimension = 0;

	assert(dimx > 0);
	assert(dimy > 0);
	assert(nmine > 0);

	setDimX(jeu, dimx);
	setDimY(jeu, dimy);
	setNMine(jeu, nmine);

	dimension = getDimX(jeu) * getDimY(jeu);

	jeu->cases = (Case *)malloc(sizeof(Case) * dimension);


	for(i = 0; i < dimension; i++)
		initCase(&jeu->cases[i]);
}

void
detruireGrille(Grille * jeu)
{
	setDimY(jeu, 0);
	setDimX(jeu, 0);

	free(jeu->cases);
	jeu->cases = NULL;
}

void
placeBombes(Grille * jeu)
{

	int x;
	int y;
	int mine;

	x = 0;
	y = 0;
	mine = 0;

	for(mine = 0; mine < getNMine(jeu); mine++)
	{
		do
		{
			x = rand() % (getDimX(jeu) - 2) + 1;
			y = rand() % (getDimY(jeu) - 2) + 1;
		}
		while(0 != getValeur(jeu->cases[y * getDimX(jeu) + x]));



		setValeur(&jeu->cases[y * getDimX(jeu) + x], MINE);
	}
}

void
compteBombesVoisines(Grille * jeu)
{
	int i;
	int j;
	int k;
	int l;

	for(i = 1; i < getDimX(jeu) - 1; i++)
	{

		for(j = 1; j < getDimY(jeu) - 1; j++)
		{
			if(getValeur(jeu->cases[j * getDimX(jeu) + i]) != MINE)
			{
				for(k = i - 1; k <= i + 1; k++)
				{
					for(l = j - 1; l <= j + 1; l++)
						if(getValeur(jeu->cases[l * getDimX(jeu) + k]) == MINE)
							incrementerCase(&jeu->cases[j * getDimX(jeu) + i]);
				}
			}
		}
	}

}

int calculCasesRestantes(const Grille *jeu)
{
    int i, j, total;

    total = (jeu->dimy-2) * (jeu->dimx-2) - getNMine(jeu);
    
    for(j = 1 ; j < getDimY(jeu) - 1; j++)
	{
		for(i = 1; i < getDimX(jeu) - 1; i++)
		{
			if(estDecouverte(getCase(jeu, i, j)))
			{
            	total--;
            }
		}
    }
    return total;
}


void decouvrirZero(Grille *jeu, const int x, const int y)
{
	int i,j;

	assert(x >= 0 && x<getDimX(jeu)-1);
	assert(y >= 0 && y<getDimY(jeu)-1);

	for(i=x-1; i<=x+1; i++)
   	{
    	if( (i>=1) && i<getDimX(jeu)-1 )
    	{
    		for(j=y-1; j<=y+1; j++)
    		{
    			if( (j>=1) && j<getDimY(jeu)-1 )
    			{
    				if( (getValeur(getCase(jeu,i,j)) == 0) && !estDecouverte(getCase(jeu,i,j)))
    				{
    					setDecouverte(getCasePtr(jeu,i,j), TRUE);
    					decouvrirZero(jeu,i,j);
    				}
    				if( (getValeur(getCase(jeu,i,j)) != 0) && !estDecouverte(getCase(jeu,i,j)))
    				{
    					setDecouverte(getCasePtr(jeu,i,j), TRUE);
    				}
    			}
    		}
    	}
  	}
}

void gestionDrapeau(Grille *jeu, const int x, const int y)
{
	Case *c;

	assert(x >= 0 && x<getDimX(jeu)-1);
	assert(y >= 0 && y<getDimY(jeu)-1);

	if(!drapeauPresent(getCase(jeu,x,y)) && !estDecouverte(getCase(jeu,x,y)))
	{
		c = getCasePtr(jeu,x,y);
 		poserDrapeau(c);
	}
	else
	{
		c = getCasePtr(jeu,x,y);
		retirerDrapeau(c);
	}
}

int traitementGrille(Grille *jeu, const int x, const int y)
{
	int valeur;

	assert(x >= 0 && x<getDimX(jeu)-1);
	assert(y >= 0 && y<getDimY(jeu)-1);

	if(!drapeauPresent(getCase(jeu, x, y)))
    {
    	valeur=getValeur(getCase(jeu, x, y));
        if(valeur == 0)
        {
        	decouvrirZero(jeu, x, y);
        }
        else
        	setDecouverte(getCasePtr(jeu, x, y),TRUE);

        if(valeur == MINE)
        {
        	decouvrirMines(jeu); /* pour afficher la solution une fois perdu */
        	return MINE;
        }
	}
	return calculCasesRestantes(jeu);
}

void decouvrirMines(Grille *jeu)
{
	int i, j;
	
	for(j = 1 ; j < getDimY(jeu) - 1; j++)
		for(i = 1; i < getDimX(jeu) - 1; i++)
			if(getValeur(getCase(jeu,i,j)) == MINE && !estDecouverte(getCase(jeu, i, j)))
			{
				if(drapeauPresent(getCase(jeu,i,j)))
					retirerDrapeau(getCasePtr(jeu,i,j));
            	setDecouverte(getCasePtr(jeu,i,j), TRUE);
            }
}
